package nancal.mp.mvc.dev

import io.swagger.annotations.*
import nancal.mp.client.node.NodeJsClient
import nancal.mp.db.mongo.*
import nancal.mp.db.mongo.entity.*
import nancal.mp.db.mongo.entity.dev.*
import nbcp.base.annotation.*
import nbcp.base.annotation.mvc.*
import nbcp.base.comm.*
import nbcp.base.extend.*
import nbcp.base.model.HttpInvoke
import nbcp.mvc.HttpContext
import nbcp.mvc.sys.*
import nbcp.myoql.db.*
import nbcp.myoql.db.mongo.*
import nbcp.web.*

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.mongodb.core.query.*
import org.springframework.web.bind.annotation.*
import java.time.*
import javax.servlet.http.*

/**
 * Created by CodeGenerator at 2023-10-19 02:02:00
 */
@Api(description = "Api故事", tags = arrayOf("ApiStory"))
@RestController
@RequestMapping("/dev/api-story")
class ApiStoryAutoController {

    @ApiOperation("列表")
    @PostMapping("/list")
    fun list(
        id: String, //当列表列新一条后，刷新时使用
        productLineCode: String,
        name: String,
        search: String,
        @org.springframework.web.bind.annotation.RequestBody query: PagerModel<Any?>,
        request: HttpServletRequest
    ): ListResult<ApiStory> {

        mor.dev.apiStory.query()
            .apply {
                if (id.HasValue) {
                    this.where { it.id mongoEquals id }
                }
                if (productLineCode.HasValue) {
                    this.where { it.productLine.code mongoEquals productLineCode }
                }

                if (name.HasValue) {
                    this.where { it.name mongoLike name }
                }

                if (search.HasValue) {
                    this.linkOr(
                        { it.apis.apiDefine.name mongoLike search },
                        { it.apis.apiDefine.url mongoLike search },
                        { it.apis.apiDefine.group mongoLike search },
                        { it.apis.apiDefine.remark mongoLike search }
                    )
                }
            }
            .withPager(query)
            .toListResult()
            .apply {
                return this;
            }
    }

    @ApiOperation("详情")
    @PostMapping("/detail/{id}")
    fun detail(
        @Require id: String,
        request: HttpServletRequest
    ): ApiResult<ApiStory> {
        mor.dev.apiStory.queryById(id)
            .toEntity()
            .apply {
                if (this == null) {
                    return ApiResult.error("找不到数据")
                }

                return ApiResult.of(this)
            }
    }

    @ApiOperation("更新")
    @PostMapping("/save")
    fun save(
        @org.springframework.web.bind.annotation.RequestBody entity: ApiStory,
        request: HttpServletRequest
    ): ApiResult<String> {
        //鉴权
        var userId = request.UserId;

        mor.dev.apiStory.updateWithEntity(entity)
            .withColumns(request.requestParameterKeys)
            .run {
                if (entity.id.HasValue) {
                    return@run this.execUpdate()
                } else {
                    return@run this.execInsert()
                }
            }
            .apply {
                if (this == 0) {
                    return ApiResult.error("更新失败")
                }

                return ApiResult.of(entity.id)
            }
    }

    @ApiOperation("删除")
    @PostMapping("/delete/{id}")
    fun delete(
        @Require id: String,
        request: HttpServletRequest
    ): JsonResult {
        //鉴权
        var userId = request.UserId

        var entity = mor.dev.apiStory.queryById(id).toEntity()
        if (entity == null) {
            return JsonResult.error("找不到数据")
        }

        mor.dev.apiStory.deleteById(id)
            .exec()
            .apply {
                if (this == 0) {
                    return JsonResult.error("删除失败")
                }
                //实体上配置垃圾箱功能，可物理删除，会自动移到垃圾箱。
                return JsonResult()
            }
    }

    @ApiOperation("同步")
    @PostMapping("/sync-api")
    fun syncApi(@Require id: String): JsonResult {
        var api = mor.dev.apiStory.queryById(id).toEntity()
            .must()
            .elseThrow { "找不到数据" };

        var apiIds = api.apis.map { it.apiDefine.id };

        var apis = mor.dev.apiDefine.query()
            .where { it.id mongoIn apiIds }
            .toList();

        api.apis.forEach { instance ->
            instance.apiDefine = apis.first { it.id == instance.apiDefine.id }
        }

        mor.dev.apiStory.updateWithEntity(api).execUpdate();
        return JsonResult();
    }

    @ApiOperation("删除")
    @PostMapping("/run/{id}")
    fun run(
        @Require id: String
    ): JsonResult {
        var api = mor.dev.apiStory.queryById(id).toEntity()
            .must()
            .elseThrow { "找不到数据" };

        if (api.apiAddress.isNullOrEmpty()) {
            throw RuntimeException("apiAddress 不能为空");
        }

        if (api.apis.size == 0) {
            throw RuntimeException("没有 apis");
        }

        var ret = nodeJsClient.runStory(id);
        if (HttpInvoke.lastRequest!!.result!!.status != 200) {
            return JsonResult.error("执行报错! 状态码:" + HttpInvoke.lastRequest!!.result!!.status);
        }

        if (ret.hasError) {
            return JsonResult.error(ret.msg);
        }

        return JsonResult();
    }

    class RunApiDTO {
        var parameters = mutableListOf<KeyValueScript>()
        var postBody = ""
        var postBodyScript = ""
        var remark = ""
    }


    @Autowired
    lateinit var nodeJsClient: NodeJsClient;

    @ApiOperation("运行")
    @PostMapping("/run-api")
    fun runApi(
        @Require id: String,
        @Require index: Int,
        @org.springframework.web.bind.annotation.RequestBody data: RunApiDTO
    ): ApiResult<ApiStory> {

        var api = mor.dev.apiStory.queryById(id).toEntity()
            .must()
            .elseThrow { "找不到数据" };

        if (api.apiAddress.isNullOrEmpty()) {
            throw RuntimeException("apiAddress 不能为空");
        }

        if (index >= api.apis.size) {
            throw RuntimeException("index 超出索引范围");
        }

        api.apis[index].parameters = data.parameters
        api.apis[index].postBody = data.postBody
        api.apis[index].postBodyScript = data.postBodyScript
        api.apis[index].remark = data.remark

        mor.dev.apiStory.updateById(api.id)
            .set(mor.dev.apiStory.apis + "." + index.toString(), api.apis[index])
            .exec();

        var ret = nodeJsClient.runApi(id, index);

        if (HttpInvoke.lastRequest!!.result!!.status != 200) {
            return ApiResult.error("执行报错! 状态码:" + HttpInvoke.lastRequest!!.result!!.status);
        }
        if (ret.hasError) {
            return ApiResult.error(ret.msg);
        }

        api = mor.dev.apiStory.queryById(id).toEntity()
            .must()
            .elseThrow { "找不到数据" };

        return ApiResult.of(api);
    }
}